package 同步互斥;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;

class Buffer {

    private LinkedList<Object> list = new LinkedList<Object>();
    // 互斥量，控制buffer的互斥访问
    final Semaphore mutex = new Semaphore(1);

    // canProduceCount可以生产的数量（表示缓冲区可用的数量）。 通过生产者调用acquire，减少permit数目
    final Semaphore canProduceCount = new Semaphore(10);

    // canConsumerCount可以消费的数量。通过生产者调用release，增加permit数目
    final Semaphore canConsumerCount = new Semaphore(0);

        public void out()
        {
                try {
                       canProduceCount.acquire();//顺序不能颠倒，否则会造成死锁。
                        mutex.acquire();
                        list.add(new Object());
                        System.out.println("【生产者" + Thread.currentThread().getName()
                                + "】生产一个产品，现库存" + list.size());
                }
                catch (Exception e) {
                        e.printStackTrace();
                } finally {
                        mutex.release();
                        canConsumerCount.release();
                }
        }
        public void in()
        {
                try {
                        canConsumerCount.acquire();//顺序不能颠倒，否则会造成死锁。
                        mutex.acquire();
                        list.remove();
                        System.out.println("【消费者" + Thread.currentThread().getName()
                                + "】消费一个产品，现库存" + list.size());
                } catch (Exception e) {
                        e.printStackTrace();
                } finally {
                        mutex.release();
                       canProduceCount.release();
                }
        }


}
class  Producer implements Runnable{
    Buffer buffer;

    public Producer(Buffer buffer){
        this.buffer = buffer;
    }
    public void run(){
        while(true){
            try{
                Thread.sleep(100);
                buffer.out();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }

}
class  Consumer implements Runnable{
     Buffer buffer;
    public Consumer(Buffer buffer){
        this.buffer = buffer;
    }
    public void run(){
        while(true){
            try{
                Thread.sleep(100);
                buffer.in();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }

}


public class Demo
{
    public static void main(String[] args) {
            Buffer buffer=new Buffer();
            Thread p1 = new Thread(new Producer(buffer));
            Thread p2 = new Thread(new Producer(buffer));
            Thread p3 = new Thread(new Producer(buffer));

            Thread c1 = new Thread(new Consumer(buffer));
            Thread c2 = new Thread(new Consumer(buffer));
            Thread c3 = new Thread(new Consumer(buffer));

            p1.start();
            p2.start();
            p3.start();
            c1.start();
            c2.start();
            c3.start();

    }

}